(function () {
  // 页面被作为iframe时不加载
  if (self != top) {
    return;
  }

  if (window.WebViewJavascriptBridge) {
    console.log('bridge was inited');
    return;
  }

  if (!window.android) {
    window.android = {
      onClearOnlineCache: (...args) => {
        // console.log('onClearOnlineCache', ...args);
      },
      onActionEvent: (...args) => {
        // console.log('onActionEvent', ...args);
      },
    };
  }

  var messagingIframe;
  var sendMessageQueue = [];
  var receiveMessageQueue = [];
  var messageHandlers = {};
  var CUSTOM_PROTOCOL_SCHEME = 'wvjbscheme';
  var QUEUE_HAS_MESSAGE = '__WVJB_QUEUE_MESSAGE__';
  var responseCallbacks = {};
  var uniqueId = 1;
  var receiveEventQueue = [];
  var eventHandlers = {};
  var handlerNameCnt = {};

  function registerListener(action, handler) {
    var actionHandlers = eventHandlers[action];
    if (handler) {
      if (actionHandlers) {
        actionHandlers.push(handler);
      } else {
        actionHandlers = [];
        actionHandlers.push(handler);
        eventHandlers[action] = actionHandlers;
      }
    }
  }

  function unRegisterListener(action, handler) {
    var actionHandlers = eventHandlers[action];
    if (handler && actionHandlers) {
      var resultHandlers = [];
      for (var i = 0; i < actionHandlers.length; i++) {
        if (handler != actionHandlers[i]) {
          resultHandlers.push(actionHandlers[i]);
        }
      }
      eventHandlers[action] = resultHandlers;
    } else {
      eventHandlers[action] = [];
    }
  }

  function _handleActionEventFromObjC(action, message) {
    if (receiveEventQueue) {
      receiveEventQueue.push({ action: action, message: message });
    } else {
      _dispatchActionEvent(action, message);
    }
  }

  function _dispatchActionEvent(action, message) {
    console.log(action + ':' + message);
    var handlers = eventHandlers[action];
    if (handlers && handlers.length != 0) {
      for (var i = 0; i < handlers.length; i++) {
        var handler = handlers[i];
        _sendActionEvent(handler, message);
      }
    } else {
      var handler = WebViewJavascriptBridge._messageHandler;
      var messageAll = { action: action, message: JSON.parse(message) };
      _sendActionEvent(handler, JSON.stringify(messageAll));
    }
  }

  function _sendActionEvent(handler, message) {
    if (handler) {
      try {
        if (message) {
          handler(JSON.parse(message));
        } else {
          handler();
        }
      } catch (exception) {
        if (typeof console != 'undefined') {
          console.log(
            'WebViewJavascriptBridge: WARNING: javascript _sendActionEvent()! ' +
              JSON.stringify(message) +
              ' ' +
              exception
          );
        }
      }
    }
  }

  function init(messageHandler) {
    if (WebViewJavascriptBridge._messageHandler) {
      // throw new Error('WebViewJavascriptBridge.init called twice');
    }
    WebViewJavascriptBridge._messageHandler = messageHandler;
    var receivedMessages = receiveMessageQueue || [];
    receiveMessageQueue = null;
    for (var i = 0; i < receivedMessages.length; i++) {
      _dispatchMessageFromObjC(receivedMessages[i]);
    }
    var receiveEvents = receiveEventQueue || [];
    receiveEventQueue = null;
    for (var j = 0; j < receiveEvents.length; j++) {
      var event = receiveEvents[j];
      _dispatchActionEvent(event.action, event.message);
    }
  }

  function send(data, responseCallback) {
    _doSend({ data: data }, responseCallback);
  }

  function registerHandler(handlerName, handler) {
    messageHandlers[handlerName] = handler;
  }

  function callHandler(handlerName, data, responseCallback) {
    _doSend({ handlerName: handlerName, data: data }, responseCallback);
  }

  function callOnlineHandler(handlerName, onlineId, data) {
    _doSend({ handlerName: handlerName, onlineId: onlineId, data: data });
  }

  function clearOnlineHandler(onlineId) {
    var data = { onlineId: onlineId };
    window.android.onClearOnlineCache(JSON.stringify(data));
  }

  function _doSend(message, responseCallback) {
    if (responseCallback) {
      // var callbackId = "cb_" + uniqueId++ + "_" + new Date().getTime();
      // 重写id拼接规则，便于手动调用 cb_事件调用次数_事件名
      var callbackId =
        'cb_' +
        message.handlerName +
        '_' +
        (handlerNameCnt[message.handlerName]
          ? handlerNameCnt[message.handlerName]++
          : (handlerNameCnt[message.handlerName] = 1));

      // 将callbackId作为函数名，让后端能给给到这个函数
      responseCallback.__name = callbackId;
      responseCallbacks[callbackId] = responseCallback;
      message['callbackId'] = callbackId;
    }
    sendMessageQueue.push(message);
    //messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + '://' + QUEUE_HAS_MESSAGE
    window.android.onActionEvent(_fetchQueue());
  }

  function _fetchQueue() {
    var messageQueueString = JSON.stringify(sendMessageQueue);
    sendMessageQueue = [];
    return messageQueueString;
  }

  function _dispatchMessageFromObjC(messageJSON) {
    setTimeout(function _timeoutDispatchMessageFromObjC() {
      var message = JSON.parse(messageJSON);
      var messageHandler;
      //alert(messageJSON)
      if (message.responseId) {
        var responseCallback = responseCallbacks[message.responseId];
        if (!responseCallback) {
          return;
        }
        responseCallback(message.responseData);
        delete responseCallbacks[message.responseId];
      } else {
        var responseCallback;
        if (message.callbackId) {
          var callbackResponseId = message.callbackId;
          responseCallback = function (responseData) {
            _doSend({
              responseId: callbackResponseId,
              responseData: responseData,
            });
          };
        }

        var handler = WebViewJavascriptBridge._messageHandler;
        if (message.handlerName) {
          handler = messageHandlers[message.handlerName];
        }

        //alert(handler+message.responseData)
        try {
          handler(message.responseData, responseCallback);
        } catch (exception) {
          if (typeof console != 'undefined') {
            console.log(
              'WebViewJavascriptBridge: WARNING: javascript handler throw. ' + JSON.stringify(message) + ' ' + exception
            );
          }
        }
      }
    });
  }

  function _handleMessageFromObjC(messageJSON) {
    if (receiveMessageQueue) {
      receiveMessageQueue.push(messageJSON);
    } else {
      _dispatchMessageFromObjC(messageJSON);
    }
  }

  window.WebViewJavascriptBridge = {
    init: init,
    send: send,
    registerHandler: registerHandler,
    callHandler: callHandler,
    callOnlineHandler: callOnlineHandler,
    clearOnlineHandler: clearOnlineHandler,
    registerListener: registerListener,
    unRegisterListener: unRegisterListener,
    _handleActionEventFromObjC: _handleActionEventFromObjC,
    _fetchQueue: _fetchQueue,
    _handleMessageFromObjC: _handleMessageFromObjC,
    _inner: {
      sendMessageQueue,
      receiveMessageQueue,
      messageHandlers,
      responseCallbacks,
      receiveEventQueue,
      eventHandlers,
    },
  };

  var doc = document;
  var readyEvent = doc.createEvent('Events');
  readyEvent.initEvent('WebViewJavascriptBridgeReady');
  readyEvent.bridge = WebViewJavascriptBridge;
  doc.dispatchEvent(readyEvent);
})();
